package com.h6.crm.service.Impl;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.UUID;

import org.springframework.stereotype.Service;
import org.springframework.util.ResourceUtils;
import org.springframework.web.multipart.MultipartFile;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.h6.crm.entity.Attachment;
import com.h6.crm.mapper.AttachmentMapper;
import com.h6.crm.service.AttachmentService;
import com.h6.crm.util.Constant;
import com.h6.crm.util.pojo.ResultCode;
import com.h6.crm.util.pojo.ServiceException;
import com.h6.crm.util.pojo.vo.UploadFileVO;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class AttachmentServiceImpl extends ServiceImpl<AttachmentMapper, Attachment> implements AttachmentService {

    @Override
    public void dealFile(Long fileId, Long entityId, Integer fileType, String remark) throws Exception {
        Attachment needDeletedAttachment = getAttachment(entityId, fileType);
        if (ObjectUtils.isNotNull(needDeletedAttachment)) {
            if (ObjectUtil.equal(fileId, needDeletedAttachment.getId())) {
                return;
            }
            removeById(needDeletedAttachment);
        }
        if (ObjectUtil.isNull(fileId)) {
            return;
        }
        Attachment attachment = getById(fileId);
        if (ObjectUtils.isNull(attachment)) {
            return;
        }
        attachment.setEntityId(entityId);
        attachment.setFileType(fileType);
        attachment.setRemark(remark);
        updateById(attachment);
    }

    @Override
    public Attachment getAttachment(Long entityId, Integer fileType) {
        return getOne(new LambdaQueryWrapper<Attachment>()
                .eq(Attachment::getEntityId, entityId)
                .eq(Attachment::getFileType, fileType));
    }

    @Override
    public String getAttachmentUrl(Long entityId, Integer fileType) {
        Attachment attachment = getAttachment(entityId, fileType);
        if (ObjectUtils.isNull(attachment)) {
            return null;
        }
        return attachment.getFilePath();
    }

    @Override
    public void downloadAttachment(HttpServletResponse response, Long fileId) {
        Attachment attachment = getById(fileId);
        if (ObjectUtil.isNull(attachment)) {
            throw new ServiceException(ResultCode.DATA_NOT_EXISTS);
        }
        String DIR_PATH;
        try {
            DIR_PATH = URLDecoder.decode(ResourceUtils.getURL("classpath:static").getPath(), StandardCharsets.UTF_8);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            throw new ServiceException(ResultCode.DATA_NOT_EXISTS);
        }
        File file = new File(DIR_PATH + attachment.getFilePath());
        if (!file.exists()) {
            throw new ServiceException(ResultCode.DATA_NOT_EXISTS);
        }
        response.reset();
        response.setContentType("application/octet-stream");
        response.setCharacterEncoding("utf-8");
        response.setContentLength((int) file.length());
        response.setHeader("Content-Disposition", "attachment;filename=" + attachment.getFileName());
        try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));) {
            byte[] buff = new byte[1024];
            OutputStream os = response.getOutputStream();
            int i = 0;
            while ((i = bis.read(buff)) != -1) {
                os.write(buff, 0, i);
                os.flush();
            }
        } catch (IOException e) {
            log.error("{}", e);
            throw new ServiceException(ResultCode.ATTACHMENT_DOWNLOAD_FAILD);
        }
    }

    @Override
    @SuppressWarnings("null")
    public Attachment uploadAttachment(UploadFileVO fileVO) {
        MultipartFile multipartFile = fileVO.getAttachment();
        String fileName = multipartFile.getOriginalFilename();
        if (StrUtil.isBlank(fileName)) {
            throw new ServiceException(ResultCode.ATTACHMENT_NOT_NAME);
        }
        String newFileName = UUID.randomUUID().toString().replaceAll("-", "");
        byte[] bytes;
        String pathTemp;
        try {
            // 文件输出地址
            String DIR_PATH = URLDecoder.decode(ResourceUtils.getURL("classpath:static").getPath(),
                    StandardCharsets.UTF_8);
            // log.info(DIR_PATH);
            bytes = multipartFile.getBytes();
            pathTemp = Constant.UPLOAD_PATH + newFileName + fileName.substring(fileName.lastIndexOf("."));
            Path filePath = Paths.get(DIR_PATH + pathTemp);
            Files.write(filePath, bytes);
        } catch (IOException e) {
            log.error(e.toString());
            throw new ServiceException(ResultCode.ATTACHMENT_UPLOAD_FAILD);
        }
        Attachment attachment = new Attachment();
        attachment.setFilePath(pathTemp);
        attachment.setFileName(fileName);
        save(attachment);
        return attachment;
    }

    @Override
    public void dealFile(String filePath, Long entityId, Integer fileType, String remark) throws Exception {
        Attachment needDeletedAttachment = getAttachment(entityId, fileType);
        if (ObjectUtils.isNotNull(needDeletedAttachment)) {
            if (ObjectUtil.equal(filePath, needDeletedAttachment.getFilePath())) {
                return;
            }
            removeById(needDeletedAttachment);
        }
        if (StrUtil.isBlank(filePath)) {
            return;
        }
        Attachment attachment = new Attachment();
        attachment.setEntityId(entityId);
        attachment.setFileType(fileType);
        attachment.setFileName(filePath.substring(filePath.lastIndexOf("/") + 1));
        attachment.setFilePath(filePath);
        attachment.setRemark(remark);
        save(attachment);
    }

}
